package com.ly.main;


import com.ly.imp.LyDefServlet;
import com.ly.imp.LyHttpRequest;
import com.ly.imp.LyHttpResponse;
import com.ly.imp.LyStaticResponse;
import com.ly.rule.LyServlet;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpRequest;

import java.util.Map;

/**
 * @author liuyang
 */
public class LyCatHandler extends ChannelInboundHandlerAdapter {

    /**
     * 放入已经实现了LyServlet的实例
     */
    private final Map<String, LyServlet> servletMap;
    /**
     * 放名称
     */
    private final Map<String, String> nameMap;

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    /**
     * 重写通道就绪事件，当通道接收到数据之后，将数据转化成为LyRequest
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 转化是从netty的HttpRequest转化成我们自己的LyRequest
        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;
            String uri = request.uri();

            // 定个规矩，判断后缀是否包含.html，如果是则认为是访问的静态文件
            if (this.isStatic(uri)) {
                // 此时write传入文件名即可
                LyStaticResponse res = new LyStaticResponse(request, ctx);
                String fileName = uri.substring(uri.lastIndexOf("/") + 1, uri.indexOf(".html"));

                // js、image、css文件同理此处省略
                res.write(fileName + ".html");
            } else {
                String servletName = "";
                // 然后从uri中解析出servlet的名字
                if (uri.contains("/") && uri.contains("?")) {
                    servletName = uri.substring(uri.lastIndexOf("/") + 1, uri.indexOf("?"));
                }

                LyServlet servlet = new LyDefServlet();

                // 拿到简化类名之后，从map中拿到全限定类名
                if (servletMap.containsKey(servletName)) {
                    servlet = servletMap.get(servletName);
                } else if (nameMap.containsKey(servletName)) {
                    // 双重检测实例化该servlet
                    if (servletMap.get(servletName) == null) {
                        synchronized (this) {
                            if (servletMap.get(servletName) == null) {
                                String className = nameMap.get(servletName);
                                servlet = (LyServlet) Class.forName(className).newInstance();
                                servletMap.put(servletName, servlet);
                            }
                        }
                    }
                }

                // 如果上述的两个分支都没走，那么servlet就是默认的LyDefServlet
                LyHttpRequest req = new LyHttpRequest(request);
                LyHttpResponse res = new LyHttpResponse(request, ctx);

                if (request.method().name().equalsIgnoreCase("GET")) {
                    servlet.doGet(req, res);
                } else if (request.method().name().equalsIgnoreCase("POST")) {
                    servlet.doPost(req, res);
                }
            }
            ctx.close();
        }
    }

    private boolean isStatic(String url) {
        return url.contains(".html");
    }

    public LyCatHandler(Map<String, String> nameMap, Map<String, LyServlet> servletMap) {
        this.nameMap = nameMap;
        this.servletMap = servletMap;
    }
}
